module multiply3(	
			input [15:0] opnum1,
			
			input [15:0] opnum2,
			input [2:0] enable,
			input  isNeg1,
			input  isNeg2,

			
			// weng
			input [1:0] pPos1,
			input [1:0] pPos2,		
			
			input sysclk,
			
			input reset,
			
			input done,
			output reg isNeg,
			
			output reg [15:0] result1,
	
			output reg [1:0] pPosRes,		
			output reg suc
			);

			
			
			reg [31:0] result;
			reg [2:0] state;

			reg [2:0] nstate;
			reg [4:0] count;
			reg [31:0] opnum1_temp;	
			reg [2:0] pPos_result;
			reg [3:0] highPos_result;

			parameter s_init = 3'b000,
						s_add = 3'b001,
						s_shift = 3'b010,
						s_finish = 3'b011, 
						s_fix =3'b100 ;			
			initial begin	
				nstate=s_init;
			end
			
			

always @(posedge sysclk) begin
	
				state = nstate;

			end
			
			

always @(posedge sysclk) begin	
				if (reset) begin		
					nstate = s_init;		
					suc = 1'b0;
					isNeg = 1'b0;		
					count = 5'd0;		
					result = 32'b0;
					opnum1_temp=32'b0;		
				end
	else begin			
					case (state)			
						s_init: begin
							if (enable==3'b011) begin									
								result = 32'b0;									
								count = 5'd0;									
								nstate = s_add;									
								suc = 1'b0;
								opnum1_temp = opnum1;
							end
							else  begin
								nstate = s_init;
								suc = 1'b0;
							end
						end
						s_add: begin
							if (opnum2[count])
								result = result + opnum1_temp;
								nstate = s_shift;				
						end												
					s_shift: begin				  
							opnum1_temp = {opnum1_temp[30:0],1'b0};				  
							count = count+1'b1;					
							if (count==5'd16) begin						
								// nstate = s_finish;
								nstate = s_fix;
							end						
							else						
								nstate = s_add;				
						end					
						s_fix: begin
						
							if (result > 32'd9_999_999)
								highPos_result = 4'd8;
							else if (result > 32'd999_999)
								highPos_result = 4'd7;
							else if (result > 32'd99_999)
								highPos_result = 4'd6;
							else if (result > 32'd9_999)
								highPos_result = 4'd5;
							else if (result > 32'd999)
								highPos_result = 4'd4;
							else if (result > 32'd99)
								highPos_result = 4'd3;
							else if (result > 32'd9)
								highPos_result = 4'd2;
							else if (result > 32'd0)
								highPos_result = 4'd1;
							else
								highPos_result = 4'd0;
						
							pPos_result = pPos1 + pPos2;
							
							//if (highPos_result - pPos_result >= 0) begin
								case(highPos_result)
									4'd8: begin
										result = ( ( (result>>7)+ (result>>9)+ (result>>12) ) >>10 );
										case (pPos_result)
											3'd6: pPosRes = 2;
											3'd5: pPosRes = 1;
											3'd4,
											3'd3,
											3'd2,
											3'd1,
											3'd0: pPosRes = 0;
										endcase
										end
									4'd7: begin
										result = ( ( (result>>1) + (result>>7)+ (result>>8)+ (result>>12)+ (result>>15)+ (result>>16)) >>9 ); 
										case (pPos_result)
											3'd6: pPosRes = 3;
											3'd5: pPosRes = 2;
											3'd4: pPosRes = 1;
											3'd3,
											3'd2,
											3'd1,
											3'd0: pPosRes = 0;
										endcase
										end
									4'd6: begin
										if (pPos_result == 3'd6)
											result = ( ( (result>>1) + (result>>7)+ (result>>8)+ (result>>12)+ (result>>15)+ (result>>16)) >>9 ); 
										else 
											result = (( ( (result>>1) + (result>>3)+ (result>>7)+ (result>>8)+ (result>>9)+ (result>>10)+ (result>>12)+ (result>>14)+ (result>>15)+ (result>>16)+ (result>>17) ) ) >>6 );
											
										case (pPos_result)
											3'd6,
											3'd5: pPosRes = 3;
											3'd4: pPosRes = 2;
											3'd3: pPosRes = 1;
											3'd2,
											3'd1,
											3'd0: pPosRes = 0;
										endcase
										end
									4'd5: begin

										case (pPos_result)
											3'd6: begin
													pPosRes = 3;
													result = ( ( (result>>1) + (result>>7)+ (result>>8)+ (result>>12)+ (result>>15)+ (result>>16)) >>9 ); 
												end
											3'd5: begin
													pPosRes = 3;
													if(result[31:18])
														result = ( ( (result>>1) + (result>>3)+ (result>>7)+ (result>>8)+ (result>>9)+ (result>>10)+ (result>>12)+ (result>>14)+ (result>>15)+ (result>>16)+ (result>>17) ) >>6 );
													else if(result[31:7])
														result = ( ( (result>>1) + (result>>3)+ (result>>7)+ (result>>8)+ (result>>9)+ (result>>10)+ (result>>11) ) >>6 );
							   						else
														result = ( ( (result>>1) + (result>>3)+ (result>>6) ) >>6 );					
												end
											3'd4: begin
													pPosRes = 3;
													result = ( ( (result>>1) + (result>>2)+ (result>>5)+ (result>>6)+ (result>>9)+ (result>>10)+ (result>>12)) >>3 );
												end
											3'd3: begin
													pPosRes = 2;
													result = ( ( (result>>1) + (result>>2)+ (result>>5)+ (result>>6)+ (result>>9)+ (result>>10)+ (result>>12)) >>3 );
												end
											3'd2: begin
													pPosRes = 1;
													result = ( ( (result>>1) + (result>>2)+ (result>>5)+ (result>>6)+ (result>>9)+ (result>>10)+ (result>>12)) >>3 );
												end
											3'd1,
											3'd0:  begin 
													pPosRes = 0;
													result = ( ( (result>>1) + (result>>2)+ (result>>5)+ (result>>6)+ (result>>9)+ (result>>10)+ (result>>12)) >>3 );
												end
										endcase
										end
									4'd4: begin
										case (pPos_result)
											3'd6: begin
													pPosRes = 3;
													result = ( ( (result>>1) + (result>>7)+ (result>>8)+ (result>>12)+ (result>>15)+ (result>>16)) >>9 ); 
												end
											3'd5: begin
													pPosRes = 3;
													if(result[31:18])
														result = ( ( (result>>1) + (result>>3)+ (result>>7)+ (result>>8)+ (result>>9)+ (result>>10)+ (result>>12)+ (result>>14)+ (result>>15)+ (result>>16)+ (result>>17) ) >>6 );
													else if(result[31:7])
														result = ( ( (result>>1) + (result>>3)+ (result>>7)+ (result>>8)+ (result>>9)+ (result>>10)+ (result>>11) ) >>6 );
							   						else
														result = ( ( (result>>1) + (result>>3)+ (result>>6) ) >>6 );					
												end
											3'd4: begin
													pPosRes = 3;
													result = ( ( (result>>1) + (result>>2)+ (result>>5)+ (result>>6)+ (result>>9)+ (result>>10)+ (result>>12)) >>3 );
												end
											3'd3: begin
													pPosRes = 3;
												end
											3'd2: begin
													pPosRes = 2;
												end
											3'd1: begin
													pPosRes = 1;
												end
											3'd0:  begin 
													pPosRes = 0;
												end
										endcase
										end
									4'd3: begin
										case (pPos_result)
											3'd6: begin
													pPosRes = 3;
													result = 0; 
												end
											3'd5: begin
													pPosRes = 3;
													if(result[31:18])
														result = ( ( (result>>1) + (result>>3)+ (result>>7)+ (result>>8)+ (result>>9)+ (result>>10)+ (result>>12)+ (result>>14)+ (result>>15)+ (result>>16)+ (result>>17) ) >>6 );
													else if(result[31:7])
														result = ( ( (result>>1) + (result>>3)+ (result>>7)+ (result>>8)+ (result>>9)+ (result>>10)+ (result>>11) ) >>6 );
							   						else
														result = ( ( (result>>1) + (result>>3)+ (result>>6) ) >>6 );					
												end
											3'd4: begin
													pPosRes = 3;
													result = ( ( (result>>1) + (result>>2)+ (result>>5)+ (result>>6)+ (result>>9)+ (result>>10)+ (result>>12)) >>3 );
												end
											3'd3: begin
													pPosRes = 3;
												end
											3'd2: begin
													pPosRes = 2;
												end
											3'd1: begin
													pPosRes = 1;
												end
											3'd0:  begin 
													pPosRes = 0;
												end
										endcase
										end
									4'd2: begin
										case (pPos_result)
											3'd6, 3'd5: begin
													pPosRes = 3;
													result = 0; 
												end
											3'd4: begin
													pPosRes = 3;
													result = ( ( (result>>1) + (result>>2)+ (result>>5)+ (result>>6)+ (result>>9)+ (result>>10)+ (result>>12)) >>3 );
												end
											3'd3: begin
													pPosRes = 3;
												end
											3'd2: begin
													pPosRes = 2;
												end
											3'd1: begin
													pPosRes = 1;
												end
											3'd0:  begin 
													pPosRes = 0;
												end
										endcase
										end
									4'd1: begin
										case (pPos_result)
											3'd6, 3'd5, 3'd4: begin
													pPosRes = 3;
													result = 0; 
												end
											3'd3: begin
													pPosRes = 3;
												end
											3'd2: begin
													pPosRes = 2;
												end
											3'd1: begin
													pPosRes = 1;
												end
											3'd0:  begin 
													pPosRes = 0;
												end
										endcase
										end
									4'd0: begin
										pPosRes = 0;
										result = 0;
										end
								endcase
							//end else begin
							//end
							
							
							result1 = result[15:0];
							isNeg = isNeg1^isNeg2;
							suc = 1'b1;
							nstate = s_finish;
							
						end
			
						
						s_finish: begin
				  
							if (done) begin
					
								suc = 1'b0;
					
								nstate = s_init;
					
							end
				  
							else 
								nstate = s_finish;
			 	  
						end
		
					endcase
	
				end
			
end


endmodule
